﻿#region Using directives

using System;
using System.Collections.Generic;
using System.Text;

#endregion

namespace MetaHeuristics.Aco
{
    using MetaHeuristics.Aco.Collections;

    public class NeighborListAsDecisionRule  : AsDecisionRule
    {
        private int depth = 20;
        private NearestNeighborListMatrix neighbors = null;

        public override void Initialize()
        {
            base.Initialize();
            this.neighbors = new NearestNeighborListMatrix(this.Aco.Distances, this.depth);
        }


        public override void MakeDecision(Ant ant)
        {
            int c = ant.LastCity;

            float sumProbabilities = BuildWheel(ant, c);

            if (sumProbabilities == 0)
                this.ChooseBestNext(ant,c);
            else
            {
                int j = this.SpunWheel(sumProbabilities);
                ant.AddCity(j);
            }
        }

        protected override float BuildWheel(Ant ant, int c)
        {
            var selectionProbabilities = this.GetSelectionProbabilities();
            float sumProbabilities = 0;
            for (int j = 0; j < this.depth; ++j)
            {
                int neighbor = this.neighbors.Neighbors[c, j];
                if (ant.Visited(neighbor))
                    selectionProbabilities[j] = 0;
                else
                {
                    float choiceInfo = this.Aco.ChoiceInfos[c, neighbor];
                    selectionProbabilities[j] = choiceInfo;
                    sumProbabilities += choiceInfo;
                }
            }
            return sumProbabilities;
        }

        protected virtual void ChooseBestNext(Ant ant, int c)
        {
            float v=0;
            int nc = -1;

            for (int j = 0; j < this.Aco.Cities.Count; ++j)
            {
                if (!ant.Visited(j))
                {
                    float choiceInfo = this.Aco.ChoiceInfos[c, j];
                    if (choiceInfo > v)
                    {
                        nc = j;
                        v = choiceInfo;
                    }
                }
            }

            ant.AddCity(nc);
        }
    }
}
